#include <iostream>
#include <sstream>
#include <fstream>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
using namespace std;

#define MAX_LINE_OF_FILE  800000
// #define MAX_LINE_OF_FILE  8
#define MAX_FILE_NUM      256
#define MAX_LINE_LEN      512

char * lines[MAX_FILE_NUM]                = {0};
size_t lines_len[MAX_FILE_NUM]            = {0};
FILE * in_fds[MAX_FILE_NUM]               = {0};
int    in_file_num                        = 0;
int    out_file_idx                       = 0;

std::string in_path;
std::string out_path;


std::string construct_path(const std::string & prefix, int idx)
{
	if (0 == idx)
	{
		return prefix;
	}
	
	std::ostringstream oss;
	oss << prefix << "." << idx;
	return oss.str();
}

int calc_min_seq_idx()
{
	int idx     = 0;
	int min_seq = 0x7fffffff;
	int seq     = 0;

	for (int i = 0; i < in_file_num; ++ i)
	{
		if (lines[i][0] == '\0')
		{
			continue;
		}

		sscanf(lines[i], "%d", &seq);
		
		if (seq < min_seq)
		{
			idx      = i;
			min_seq  = seq;
		}
	}

	return idx;
}

void solve()
{
	for (int i = 0; i < in_file_num; ++ i)
	{
		std::string path = construct_path(in_path, i);
		in_fds[i]  = fopen(path.c_str(), "r");
		assert(in_fds[i] != NULL);

		lines[i]   = new char[MAX_LINE_LEN];
		assert(NULL != lines[i]);

		if (getline(&lines[i], &lines_len[i], in_fds[i]) < 0)
		{
			lines[i][0]  = '\0';
		}
	}

	FILE * out_fd    = NULL;
	int line_count   = 0;
	int min_seq_idx  = 0;
	int end_file_num = 0;

	while (true)
	{
		if (NULL == out_fd)
		{
			std::string path  = construct_path(out_path, out_file_idx);
			out_fd            = fopen(path.c_str(), "a+");
			assert(out_fd != NULL);
		}

		min_seq_idx  = calc_min_seq_idx();

		fprintf(out_fd, "%s\n", lines[min_seq_idx]);
		// int nwrites = fwrite(lines[min_seq_idx], sizeof(char), lines_len[min_seq_idx], out_fd);
		// assert(nwrites == lines_len[min_seq_idx]);

		if (getline(&lines[min_seq_idx], &lines_len[min_seq_idx], in_fds[min_seq_idx]) < 0)
		{
			// end-of-file
			lines[min_seq_idx][0]  = '\0';
			++ end_file_num;
		}

		++ line_count;
		if (line_count >= MAX_LINE_OF_FILE)
		{
			fclose(out_fd);
			out_fd      = NULL;
			line_count  = 0;
			++ out_file_idx;
		}

		if (end_file_num >= in_file_num)
		{
			break;
		}
	}

	for (int i = 0; i < in_file_num; ++ i)
	{
		delete [] lines[i];
	}
}

int main(int argc, char * argv[])
{
	if (argc != 4)
	{
		std::cout << "Usage: " << argv[0] << " log_prefix log_num log_out" << std::endl;
		return 0;
	}

	in_path     = argv[1];
	out_path    = argv[3];
	in_file_num = ::strtol(argv[2], NULL, 10);

	assert(in_file_num <= MAX_FILE_NUM);

	solve();

	return 0;
}

